package xin.nick.roc.consumer.proxy;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import xin.nick.roc.consumer.client.ProviderInfo;
import xin.nick.roc.consumer.client.RpcClient;
import xin.nick.roc.consumer.client.ZkRegister;
import xin.nick.rpc.common.RpcRequest;
import xin.nick.rpc.common.RpcResponse;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Objects;
import java.util.UUID;

/**
 * @author Nick
 * @date 2021/7/4
 * @description
 */
@Slf4j
public class RpcClientProxy {

    public static Object createProxy(Class serviceClass) {

        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{serviceClass}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // 开始计时
                Long startTime = System.currentTimeMillis();

                // 封装request请求对象
                RpcRequest rpcRequest = new RpcRequest();
                rpcRequest.setRequestId(UUID.randomUUID().toString());
                rpcRequest.setClassName(method.getDeclaringClass().getName());
                rpcRequest.setMethodName(method.getName());
                rpcRequest.setParameterTypes(method.getParameterTypes());
                rpcRequest.setParameters(args);
                // 拿到RpcClient对象
                RpcClient rpcClient = ProviderInfo.getRpcClientInfo();
                log.info("调用rpc: {}", rpcClient);

                try {

                    // 发送请求
                    Object responseMsg = rpcClient.send(JSON.toJSONString(rpcRequest));
                    RpcResponse rpcResponse = JSON.parseObject(responseMsg.toString(), RpcResponse.class);
                    if(Objects.nonNull(rpcResponse.getError())) {
                        throw new RuntimeException(rpcResponse.getError());
                    }
                    // 返回结果
                    Object result = rpcResponse.getResult();
                    return JSON.parseObject(result.toString(), method.getReturnType());
                } catch (Exception e) {
                    throw e;
                } finally {
                    Long responseTime = System.currentTimeMillis() - startTime;
                    String provider = rpcClient.getIp() + ":" + rpcClient.getPort();
                    ProviderInfo.getResponseTimeMap().put(provider, responseTime);
                    String path = "/provider";
                    String newTimeData = new StringBuilder(String.valueOf(System.currentTimeMillis()))
                            .append(" ")
                            .append(responseTime)
                            .toString();
                    ZkRegister.getClient().setData().forPath(path + "/" + provider, newTimeData.getBytes());
                }
            }
        });

    }

}
